/*
 * UART.c
 *
 *  Created on: Apr 14, 2010
 *      Author: iandrono
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include "uart.h"
#include "../stub/stub.h"
#include "../defines.h"
#include <math.h>
#include <util/delay.h>

typedef enum {ASYNC_NORMAL=0, ASYNC_DOUBLE, SYNC} uartMode;
typedef enum {TWO_FOUR=2400, FOUR_EIGHT=4800, NINE_SIX=9600} baudMode;
typedef enum {NO_PARITY, EVEN_PARITY, ODD_PARITY} parityMode;
typedef enum {ONE_BIT, TWO_BIT} stopBitMode;

typedef struct {
	double frequency;
	baudMode bauds;
	uartMode u2x;
	stopBitMode stop_bits;
	parityMode parity;
} uartConfig;


//Interrupciones, igual lo estoy manejando por polling
//Recive: USART_RX_vect
//Send:   USART_TX_vect
void initUart( void )
{
	int ubbr = 0;

	uartConfig config;
	config.bauds = NINE_SIX;
	config.frequency = 8000000;
	config.parity = NO_PARITY;
	config.stop_bits = ONE_BIT;
	config.u2x = ASYNC_NORMAL;

	switch( config.u2x ) {
		case ASYNC_NORMAL:
			ubbr = round(((config.frequency)/(16*config.bauds))-1);
			break;
		case ASYNC_DOUBLE:
			ubbr = ((config.frequency)/(8*config.bauds))-1;
			break;
		case SYNC:
			ubbr = ((config.frequency)/(2*config.bauds))-1;
			break;
	}

	ubbr = 51;
	//ubbr = 207;
	/* Set baud rate */
	UBRR0H = (unsigned char)(ubbr>>8);
	UBRR0L = (unsigned char)ubbr;

	//Habilito (en orden): reeiver, transmitter, interrupcion de receive
	UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);

	/* Set frame format: 8data, 2stop bit */
	/*
	 * URSEL redirects UBBRH to USRC
	 */
	//8 bits con 1 bit de stop
	//USCBSn 0 = 1 bit stop / 1 = 2 bit stop
	//UPMn1:0 Paridad = 0 disabled / 2 = par / 3 = impar
	//USCZnX = bits a transmitir

	switch( config.stop_bits ) {
		case ONE_BIT:
			break;
		case TWO_BIT:
			UCSR0C |= (1<<USBS0);
			break;
	}

	switch( config.parity ) {
		case NO_PARITY:
			break;
		case EVEN_PARITY:
			UCSR0C |= (1<<UPM01);
			break;
		case ODD_PARITY:
			UCSR0C |= (1<<UPM00)|(1<<UPM01);
			break;
	}

	//Bits a transmitir 8 fijo
	//UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);

	//El del otro
	UCSR0C |= (0<<USBS0) | (1<<UCSZ00) | (1<<UCSZ01);
}


void writeUart( unsigned char data )
{
	/* Wait for empty transmit buffer */
	while ( !( UCSR0A & (1<<UDRE0)) );
	UDR0 = data;
}

void writeStrUart( char * str )
{
	while ( *str != '\0' ) {
		writeUart((unsigned char)*str);
		str++;
	}
}

unsigned char readUart( void )
{
	/* Wait for data to be received */
	while( !(UCSR0A & (1<<RXC0)) );

	return UDR0;
}

//Interrupcion de receive
SIGNAL(USART0_RX_vect) {
	unsigned char operation = readUart();

	//PORTB = operation;
	//_delay_ms(1000);

	switch( operation ) {
		case STATIC_IMAGE:
			//Static Image: Viene una imagen
			staticImageHandler();
			break;
		case SET_TIMERCOUNTER:
			setTimerCounterHandler();
			break;
		case SET_ROWSQ:
			setRowsQHandler();
			break;
	}
}
